package com.example.interesting.desensitization.realize;

import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;

import java.io.IOException;

/**
 * @author fyw
 * @version 1.0
 * @description: 实现JsonSerializer自定义json序列化
 * @date 2024/3/09 16:14
 */
@NoArgsConstructor
@AllArgsConstructor
public class DesensitizationSerializer extends JsonSerializer<String> implements ContextualSerializer {

    /**
     * 脱敏数据类型，默认为通用的第一位保留其它为“*”
     */
    private DesensitizationEnum type;

    /**
     * 左侧保留的长度
     */
    private int leftRetentionLength;

    /**
     * 右侧保留长度
     */
    private int rightRetentionLength;


    @Override
    public void serialize(String field, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        switch (type) {
            case CHINESE_NAME:
                jsonGenerator.writeString(DesensitizedUtil.chineseName(field));
                break;
            case ID_CARD:
                jsonGenerator.writeString(DesensitizedUtil.idCardNum(field, 6, 4));
                break;
            case FIXED_PHONE:
                jsonGenerator.writeString(DesensitizedUtil.fixedPhone(field));
                break;
            case MOBILE_PHONE:
                jsonGenerator.writeString(DesensitizedUtil.mobilePhone(field));
                break;
            case ADDRESS:
                jsonGenerator.writeString(DesensitizedUtil.address(field, 6));
                break;
            case EMAIL:
                jsonGenerator.writeString(DesensitizedUtil.email(field));
                break;
            case PASSWORD:
                jsonGenerator.writeString(DesensitizedUtil.password(field));
                break;
            case CAR_LICENSE:
                jsonGenerator.writeString(DesensitizedUtil.carLicense(field));
                break;
            case BANK_CARD:
                jsonGenerator.writeString(DesensitizedUtil.bankCard(field));
                break;
            case IPV4:
                jsonGenerator.writeString(DesensitizedUtil.ipv4(field));
                break;
            case IPV6:
                jsonGenerator.writeString(DesensitizedUtil.ipv6(field));
                break;
            case FIRST_MASK:
                jsonGenerator.writeString(DesensitizedUtil.firstMask(field));
                break;
            case CUSTOM:
                //借用idCardNum的封装，实际是
                jsonGenerator.writeString(desensitizationCustom(field, leftRetentionLength, rightRetentionLength));
                break;
            default:
                throw new IllegalArgumentException("不支持的脱敏类型");
        }
    }


    @Override
    public JsonSerializer<?> createContextual(final SerializerProvider serializerProvider, final BeanProperty beanProperty) throws JsonMappingException {
        //创建上下文bean对象
        if (beanProperty != null) {
            //只针对字符类型的数据进行脱敏逻辑，注意脱敏数据需设置成字符类型
            if (ObjectUtil.equal(beanProperty.getType().getRawClass(), String.class)) {
                //获取对象属性是否存在脱敏注解
                Desensitization annotation = beanProperty.getAnnotation(Desensitization.class);
                if (annotation == null) {
                    annotation = beanProperty.getContextAnnotation(Desensitization.class);
                }
                if (annotation != null) {
                    return new DesensitizationSerializer(annotation.type(), annotation.leftRetentionLength(),
                            annotation.rightRetentionLength());
                }
            }
            //其它不做处理直接返回,获取原来的值类型序列话器，直接返回
            return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
        }
        return serializerProvider.findNullValueSerializer(null);
    }

    /**
     * 自定义脱敏实现
     */
    private String desensitizationCustom(String field, int front, int end) {
        if (StrUtil.isBlank(field)) {
            return "";
        } else if (front + end > field.length()) {
            return "";
        } else {
            return front >= 0 && end >= 0 ? StrUtil.hide(field, front, field.length() - end) : "";
        }
    }
}
